package classes.shapes
{
	import classes.fillstyle.FillStyle;
	import classes.fillstyle.bitmap.BitmapFillStyle;
	import classes.fillstyle.gradient.GradientFillStyle;
	import classes.fillstyle.line.LineFillStyle;
	import classes.fillstyle.solid.SolidFillStyle;
	
	import flash.events.Event;
	import flash.geom.Point;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;
	import flash.utils.setTimeout;

	public class Arc extends BasicShape
	{
		public static const toRadian:Number = Math.PI/180;
		public static const toAngle:Number = 180/Math.PI;
		
		private var _startAngle:Number;
		private var _endAngle:Number;
		private var _minRadius:Number;
		private var _maxRadius:Number;
		
		public function Arc(startAngle:Number, endAngle:Number, minRadius:Number, maxRadius:Number, lineStyle:FillStyle = null, fillStyle:FillStyle = null)
		{
			this._startAngle = startAngle;
			this._endAngle = endAngle;
			this._minRadius = minRadius;
			this._maxRadius = maxRadius;
			this._lineStyle = lineStyle;
			this._fillStyle = fillStyle;
			updateShape();
		}
		
		public function inArc(len:Number, angle:Number):Boolean
		{
			if((len >= _minRadius && len <= _maxRadius) && (angle >= startAngle && angle <= endAngle))
			{
				return true;
			}
			return false;
		}
		
		public function set startAngle(value:Number):void
		{
			this._startAngle = value;
			updateShape();
		}
		
		public function set endAngle(value:Number):void
		{
			this._endAngle = value;
			updateShape();
		}
		
		public function set minRadius(value:Number):void
		{
			this._minRadius = value;
			updateShape();
		}
		
		public function set maxRadius(value:Number):void
		{
			this._maxRadius = value;
			updateShape();
		}
		
		public function get startAngle():Number
		{
			return _startAngle;
		}
		
		public function get endAngle():Number
		{
			return _endAngle;
		}
		
		public function get minRadius():Number
		{
			return _minRadius;
		}
		
		public function get maxRadius():Number
		{
			return _maxRadius;
		}
		
		override protected function updateShape():void
		{
			this.graphics.clear();
			if((!_lineStyle) && (!_fillStyle)) return;
			
			if(_lineStyle) setLineStyle(_lineStyle);
			if(_fillStyle) setFillStyle(_fillStyle);
			
			//to star draw the shape
			
			var stRadian:Number = _startAngle * toRadian;
			var edRadian:Number = _endAngle * toRadian;
			
			var relAngle:Number = (edRadian - stRadian) * toAngle;
				relAngle = relAngle > 180 ? (relAngle-360) : relAngle;
				relAngle = relAngle < -180 ? (relAngle+360) : relAngle;
			
			var maxSt:Point = new Point();
			var maxEd:Point = new Point();
			var minSt:Point = new Point();
			var minEd:Point = new Point();
			
			maxSt.x = Math.cos(stRadian) * _maxRadius;
			maxSt.y = Math.sin(stRadian) * _maxRadius;
			
			maxEd.x = Math.cos(edRadian) * _maxRadius;
			maxEd.y = Math.sin(edRadian) * _maxRadius;
			
			minSt.x = Math.cos(stRadian) * _minRadius;
			minSt.y = Math.sin(stRadian) * _minRadius;
			
			minEd.x = Math.cos(edRadian) * _minRadius;
			minEd.y = Math.sin(edRadian) * _minRadius;
			
			this.graphics.moveTo(maxSt.x, maxSt.y);
			
			var i:int = 0;
			var radian:Number = 0;
			var xPos:Number = 0;
			var yPos:Number = 0;
			
			if(relAngle > 0)
			{
				for(i=0; i<relAngle; i++)
				{
					radian = stRadian+i*toRadian;
					xPos = Math.cos(radian)*maxRadius;
					yPos = Math.sin(radian)*maxRadius;
					this.graphics.lineTo(xPos, yPos);
				}
				
				this.graphics.lineTo(maxEd.x, maxEd.y);
				this.graphics.lineTo(minEd.x, minEd.y);
				
				for(i=relAngle; i>0; i--)
				{
					radian = stRadian+i*toRadian;
					xPos = Math.cos(radian)*minRadius;
					yPos = Math.sin(radian)*minRadius;
					this.graphics.lineTo(xPos, yPos);
				}
				
				this.graphics.lineTo(minSt.x, minSt.y);
				this.graphics.lineTo(maxSt.x, maxSt.y);
			}
			else
			{
				for(i=0; i>relAngle; i--)
				{
					radian = stRadian+i*toRadian;
					xPos = Math.cos(radian)*maxRadius;
					yPos = Math.sin(radian)*maxRadius;
					this.graphics.lineTo(xPos, yPos);
				}
				
				this.graphics.lineTo(maxEd.x, maxEd.y);
				this.graphics.lineTo(minEd.x, minEd.y);
				
				for(i=relAngle; i<0; i++)
				{
					radian = stRadian+i*toRadian;
					xPos = Math.cos(radian)*minRadius;
					yPos = Math.sin(radian)*minRadius;
					this.graphics.lineTo(xPos, yPos);
				}
				
				this.graphics.lineTo(minSt.x, minSt.y);
				this.graphics.lineTo(maxSt.x, maxSt.y);
			}
			
			this.graphics.endFill();
		}
		
		//------------------------
		protected var clickDuration:int = 1000;
		protected var clickTimeOutID:int = -1;
		
		protected static const OVER:String = "over";
		protected static const OUT:String = "out";
		
		protected var currentState:String = "out";
		
		public function onOver():void
		{
			if(currentState == OUT)
			{
				clickTimeOutID = setTimeout(onClick, clickDuration);
				currentState = OVER;
			}
		}
		
		public function onOut():void
		{
			if((currentState == OVER) || (clickTimeOutID != -1))
			{
				clearInterval(clickTimeOutID);
				clickTimeOutID = -1;
				currentState = OUT;
			}
		}
		
		protected function onClick():void
		{
			onOut();
			dispatchEvent(new Event(Event.CHANGE));
		}
	}
}